import 'dart:ffi';
import 'dart:typed_data';

import 'package:inmotion_protocol/base/base_factory.dart';
import 'package:inmotion_protocol/common/compact.dart';
import 'package:inmotion_protocol/common/product_version.dart';
import 'package:inmotion_protocol/common/vehicle_info.dart';
import 'package:inmotion_protocol/lorin/factory/special/euc/euc_message_factory.dart';
import 'package:inmotion_protocol/lorin/lorin_message.dart';
import 'package:inmotion_protocol/util/byte_util.dart';

class P6MessageFactory extends EucLorinSpecialMessageFactory<_P6Cmd>
    implements
        BMSLogMsgFactoryTrait<LorinMessage>,
        FullBMSFeatureMsgFactoryTrait<LorinMessage> {
  P6MessageFactory(ProductProperty productProperty) : super(productProperty);

  @override
  void initCompact(int apiVersion, VersionWrapper version) {
    compact = null;
    // 默认用V2 CMD
    compact ??= _P6CmdV2();
  }

  LorinMessage genAutoScreenOffOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.autoScreenOffCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genDaytimeRunningLightMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        (compact! as _P6CmdV2).daytimeRunningLightCmd(),
        ByteUtil.bool2Bytes(on));
  }

  @override
  LorinMessage genHeadlightOnOffMsg(
      {bool? on, bool? lowBeamOn, bool? highBeamOn, int? source, int? target}) {
    Uint8ClampedList bytes = Uint8ClampedList(2);
    bytes[0] = on == true ? 1 : 0;
    bytes[1] = on == true ? 1 : 0;
    return genSpecialOne2OneWriteMsg(compact!.headlightOnOffCmd(), bytes);
  }

  @override
  LorinMessage genSetLightEffectModeMsg(int mode,
      [Uint8ClampedList? param, int? source, int? target]) {
    if (param == null) {
      throw Exception(
          "Param [param] for 'genSetLightEffectModeMsg' must be set in P6. mode: $mode");
    }
    return genSpecialOne2OneWriteMsg(compact!.lightEffectModeCmd(),
        ByteUtil.buildBytes(ByteUtil.num2BytesLe(mode, 1), param));
  }

  LorinMessage genRequestLightEffectMsg() {
    return genSpecialOne2OneReadMsg(compact!.lightEffectModeCmd());
  }

  LorinMessage genRequestCurrentLightEffectIdMsg() {
    return genSpecialOne2OneReadMsg(compact!.lightEffectIdCmd());
  }

  LorinMessage genDisableChargeDangerAlertMsg() {
    return genSpecialOne2OneWriteMsg(
        compact!.disableChargeDangerAlertCmd(), Uint8ClampedList.fromList([1]));
  }

  LorinMessage genSetWarningLimitSpeedMsg(int speed1, int speed2) {
    Uint8ClampedList param = Uint8ClampedList(4);
    ByteUtil.num2BytesLe(speed1, 2, param, 0);
    ByteUtil.num2BytesLe(speed2, 2, param, 2);
    return genSpecialOne2OneWriteMsg(compact!.warningLimitSpeedCmd(), param);
  }

  /// 搜索轮胎压力传感器
  LorinMessage genSearchTirePressureSensorMsg() {
    return genSpecialOne2OneReadMsg(
        (compact! as _P6CmdV2).searchTirePressureSensorCmd());
  }

  /// 重置胎压传感器搜索结果
  LorinMessage genResetTirePressureSensorSearchResultMsg() {
    return genSpecialOne2OneWriteMsg(
        (compact! as _P6CmdV2).searchTirePressureSensorCmd());
  }

  @override
  LorinMessage genRequestBMSRealTimeInfoMsg(int target) {
    return genSpecialMany2ManyReadMsg(
        null, target, compact!.bmsRealTimeInfoCmd());
  }

  @override
  LorinMessage genRequestBMSFixedInfoMsg(int target) {
    return genSpecialMany2ManyReadMsg(null, target, compact!.bmsFixedInfoCmd());
  }

  @override
  LorinMessage genRequestBMSCellsVoltageInfoMsg(int target) {
    return genSpecialMany2ManyReadMsg(
        null, target, compact!.bmsCellsVoltageCmd());
  }

  @override
  LorinMessage genRequestBMSDateMsg(int target) {
    return genSpecialMany2ManyReadMsg(null, target, compact!.bmsDateCmd());
  }

  @override
  LorinMessage genRequestBMSLogMsg(int target, int index) {
    return genSpecialMany2ManyReadMsg(
        null, target, compact!.bmsLogCmd(), ByteUtil.num2BytesLe(index, 4));
  }

  @override
  LorinMessage genRequestBMSLogCountMsg(int target) {
    return genSpecialMany2ManyReadMsg(null, target, compact!.bmsLogCmd(),
        ByteUtil.num2BytesLe(0xFFFFFFFF, 4));
  }

  LorinMessage genTirePressureWarningOnOffMsg(bool on,
      [int? source, int? target]) {
    return genSpecialMany2ManyWriteMsg(
        null,
        target,
        (compact! as _P6CmdV2).tirePressureWarningOnOffCmd(),
        ByteUtil.bool2Bytes(on));
  }

  LorinMessage genSetLowTirePressureAlarmThresholdMsg(int threshold,
      [int? source, int? target]) {
    return genSpecialMany2ManyWriteMsg(
        null,
        target,
        (compact! as _P6CmdV2).lowPressureAlarmThresholdCmd(),
        ByteUtil.num2BytesLe(threshold, 2));
  }

  LorinMessage genSetLogoLightBrightnessMsg(int brightness,
      [int? source, int? target]) {
    return genSpecialMany2ManyWriteMsg(
        null,
        target,
        (compact! as _P6CmdV2).logoLightBrightnessCmd(),
        ByteUtil.num2BytesLe(brightness, 1));
  }

  LorinMessage genSetTurnSignalModeMsg(int mode, [int? source, int? target]) {
    return genSpecialMany2ManyWriteMsg(
        null,
        target,
        (compact! as _P6CmdV2).turnSignalModeCmd(),
        ByteUtil.num2BytesLe(mode, 1));
  }

  LorinMessage genSetBermAngleMsg(int angle, [int? source, int? target]) {
    return genSpecialMany2ManyWriteMsg(null, target,
        compact!.bermAngleCmd(), ByteUtil.num2BytesLe(angle, 1));
  }

  LorinMessage genSetOutputThresholdMsg(int tiltBack, int warning1, int warning2, [int? source, int? target]) {
    Uint8ClampedList tiltBackBytes = ByteUtil.num2BytesLe(tiltBack * 100, 2);
    Uint8ClampedList warning1Bytes = ByteUtil.num2BytesLe(warning1 * 100, 2);
    Uint8ClampedList warning2Bytes = ByteUtil.num2BytesLe(warning2 * 100, 2);
    return genSpecialMany2ManyWriteMsg(null, target,
        compact!.outputThresholdCmd(), ByteUtil.buildBytes(tiltBackBytes, warning1Bytes, warning2Bytes));
  }

  LorinMessage genSetChargeLimitMsg(int limit, [int? source, int? target]) {
    return genSpecialMany2ManyWriteMsg(null, target,
        compact!.chargeLimitCmd(), ByteUtil.num2BytesLe(limit, 1));
  }

  LorinMessage genSetMaxChargeCurrentMsg(int currentAc220, int currentAc110, [int? source, int? target]) {
    Uint8ClampedList currentAc220Bytes = ByteUtil.num2BytesLe(currentAc220, 1);
    Uint8ClampedList currentAc110Bytes = ByteUtil.num2BytesLe(currentAc110, 1);
    return genSpecialMany2ManyWriteMsg(null, target,
        compact!.maxChargeCurrentCmd(), ByteUtil.buildBytes(currentAc220Bytes, currentAc110Bytes));
  }

}

abstract class _P6Cmd extends EucCmdCompact implements FullBMSFeatureCmdTrait {
  int autoLowHighBeamOnOffCmd();

  int autoScreenOffCmd();

  int speedThrOfLowHighBeamSwitchCmd();

  int bmsLogCmd();

  int disableChargeDangerAlertCmd() {
    return 0;
  }

  int warningLimitSpeedCmd() {
    return 62;
  }

  int bermAngleCmd() {
    return 58;
  }

  int outputThresholdCmd() {
    return 76;
  }

  @override
  int bermAngleModeCmd() {
    return 67;
  }

  int chargeLimitCmd() {
    return 56;
  }

  int maxChargeCurrentCmd() {
    return 57;
  }

}

class _P6CmdV1 extends _P6Cmd {
  @override
  int autoHeadlightCmd() {
    return 47;
  }

  @override
  int autoScreenOffCmd() {
    return 61;
  }

  @override
  int autoHeadlightBrightnessThrCmd() {
    return 42;
  }

  @override
  int brightnessOfHeadlightCmd() {
    return 43;
  }

  @override
  int calibrateImuCmd() {
    return 66;
  }

  @override
  int deviceNameCmd() {
    return 12;
  }

  @override
  int headlightOnOffCmd() {
    return 64;
  }

  @override
  int lightEffectIdCmd() {
    return 45;
  }

  @override
  int passwordCmd() {
    return 10;
  }

  @override
  int passwordTypeCmd() {
    return 11;
  }

  @override
  int remainderRangeEstimateCmd() {
    return 63;
  }

  @override
  int assistBalanceCmd() {
    return 0;
  }

  @override
  int soundWaveCmd() {
    return 57;
  }

  @override
  int soundWaveSensitivityCmd() {
    return 56;
  }

  @override
  int speedThrOfLowHighBeamSwitchCmd() {
    return 0;
  }

  @override
  int speedingBrakingCmd() {
    return 66;
  }

  @override
  int speedingBrakingSensitivityCmd() {
    return 64;
  }

  @override
  int transportationModeCmd() {
    return 50;
  }

  @override
  int usbPowerCmd() {
    return 60;
  }

  @override
  int lightEffectModeCmd() {
    return 51;
  }

  @override
  int autoLowHighBeamOnOffCmd() {
    return 47;
  }

  @override
  int bmsCellsVoltageCmd() {
    return 2;
  }

  @override
  int bmsDateCmd() {
    return 3;
  }

  @override
  int bmsFixedInfoCmd() {
    return 4;
  }

  @override
  int bmsLogCmd() {
    return 5;
  }

  @override
  int bmsRealTimeInfoCmd() {
    return 1;
  }
}

class _P6CmdV2 extends _P6CmdV1 {
  int daytimeRunningLightCmd() => 78;

  @override
  int speedThrOfLowHighBeamSwitchCmd() {
    return 48;
  }

  @override
  int remainderRangeEstimateCmd() {
    return 63;
  }

  @override
  int speedingBrakingSensitivityCmd() {
    return 64;
  }

  @override
  int assistBalanceCmd() {
    return 65;
  }

  @override
  int speedingBrakingCmd() {
    return 66;
  }

  int logoLightBrightnessCmd() {
    return 68;
  }

  int lowPressureAlarmThresholdCmd() {
    return 77;
  }

  int tirePressureWarningOnOffCmd() {
    return 79;
  }

  int turnSignalModeCmd() {
    return 48;
  }

  @override
  int headlightOnOffCmd() {
    return 80;
  }

  @override
  int playSoundItemCmd() {
    return 81;
  }

  @override
  int calibrateImuCmd() {
    return 82;
  }

  @override
  int disableChargeDangerAlertCmd() {
    return 83;
  }

  int searchTirePressureSensorCmd() {
    return 84;
  }
}

class PublicP6CmdV2 extends _P6CmdV2 {}
